home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
glass
/
glass.lha
/
GLASS
/
contsens
/
unification.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-31
|
27KB
|
998 lines
/* Copyright (C) 1990 Riet Oolman
This file is part of GLASS.
GLASS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GLASS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GLASS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* file: unification.c
author: H. Oolman
last changed: 13-7-'90
purpose: unification of types for type-checking of GLASS
modifications:
updated for new version of Glass
p2c translated, tmc access procs
*/
#include "handleds.h"
#include "check.ds.h"
#include "check.var.h"
#include "check.afuncs.h"
#include "errorenv.h"
#include "unification.h"
/* unification procedures for types. The types can have < relations */
Void becomes(t1, t2)
typcrec *t1, *t2;
{
/* t1 (tag UNKNOWN or SOME) should be changed to t2. This is done by
indirection. Therefore care must be taken to let all occurrences of t1 with
the same number have the same record. On inspecting
a type, these INDIRs should always be skipped */
t1->kind = kindINDIR;
t1->INDIR.tcind = t2;
}
boolean occurs(n, t)
long n;
typcrec *t;
{
/* see if typename n does not occur as a real subpart of type t (this is not
allowed) */
while (t->kind == kindINDIR) t = t->INDIR.tcind;
switch (t->kind) {
case kindUNKNOWN:
return (t->UNKNOWN.unknm == n);
break;
case kindSOME:
if (t->SOME.somnr == n)
return true;
else
return occurs(n, t->SOME.tcpart);
break;
case kindSINGLEARROW:
return occurs(n, t->SINGLEARROW.tcarg) | occurs(n, t->SINGLEARROW.tcres);
break;
case kindCT:
return occurs(n, t->CT.tcfirst) | occurs(n, t->CT.tcrest);
break;
case kindSYSTY:
return occurs(n, t->SYSTY.syscomp);
break;
case kindINT:
case kindFLOAT:
case kindBOOL:
case kindSTRING:
case kindEMPTYT:
case kindBASETY:
case kindAPS:
case kindLOC:
return false;
break;
case kindALL:
return occurs(n, t->ALL.tcall);
break;
}
} /* occurs */
boolean restrictable(mustendemp, mustconn, ty, vl)
boolean mustendemp, mustconn;
typcrec *ty;
val vl;
{
/* if mustendemp then ty must be a (tuple) type ending in the empty
type; if mustconn ty may only be a type fit for connections. Error
if conditions not fullfilled.
UNKNOWNs in ty are restricted (in their mustendemp and mustconn fields)
to the demands
The result tells if restricting could be done without errors
vl: the expression that causes restrictable to be called */
boolean rb;
rb = true;
if (!(mustendemp || mustconn)) return rb;
while (ty->kind == kindINDIR) ty = ty->INDIR.tcind;
switch (ty->kind) {
case kindSYSTY:
case kindINT:
case kindFLOAT:
case kindBOOL:
case kindSTRING:
case kindAPS:
case kindSINGLEARROW:
if (mustendemp) {
error(15L, ty, NULL, NULL, vl, false);
rb = false;
}
if (mustconn) {
rb = false;
error(16L, ty, NULL, NULL, vl, false);
}
break;
case kindEMPTYT: /* always right */
break;
case kindLOC:
if (mustendemp) {
rb = false;
error(15L, ty, NULL, NULL, vl, false);
}
break;
case kindCT:
rb = restrictable(false, mustconn, ty->CT.tcfirst, vl) |
restrictable(false, mustconn, ty->CT.tcrest, vl);
break;
/* assumption: CT only constructed with mustendemp satisfied */
case kindALL:
rb = false;
error(10L, NULL, NULL, Buildsymbol("restrictable", 12L), NULL, false);
break;
case kindUNKNOWN:
ty->UNKNOWN.mustendemp = (ty->UNKNOWN.mustendemp || mustendemp);
ty->UNKNOWN.mustconn = (ty->UNKNOWN.mustconn || mustconn);
break;
case kindSOME:
rb = restrictable(false, mustconn, ty->SOME.tcpart, vl);
break;
case kindBASETY:
if (mustendemp) {
rb = false;
error(15L, ty, NULL, NULL, vl, false);
}
break;
}
return rb;
} /* restrictable */
Local Void largerdir(dg1, dg2, direrfnd, vl)
dirgraphrec *dg1, *dg2;
boolean *direrfnd;
val vl;
{
/* dg1 should be larger than dg2. dgi are directions of a system's type.
? < none, ! < none
direrfnd<-> direction error already found and notified
vl: for which an error can be found */
switch (dg1->kind) {
case kindCd:
switch (dg2->kind) {
case kindCd:
largerdir(dg1->Cd.dgfirst, dg2->Cd.dgfirst, direrfnd, vl);
largerdir(dg1->Cd.dgrest, dg2->Cd.dgrest, direrfnd, vl);
break;
case kindSd:
largerdir(dg1->Cd.dgfirst, dg2->Sd.dgpart, direrfnd, vl);
largerdir(dg1->Cd.dgrest, dg2, direrfnd, vl);
break;
case kindOd:
largerdir(dg1->Cd.dgfirst, dg2, direrfnd, vl);
largerdir(dg1->Cd.dgrest, dg2, direrfnd, vl);
break;
}
break;
case kindSd:
switch (dg2->kind) {
case kindCd:
largerdir(dg1->Sd.dgpart, dg2->Cd.dgfirst, direrfnd, vl);
largerdir(dg1, dg2->Cd.dgrest, direrfnd, vl);
break;
case kindSd:
largerdir(dg1->Sd.dgpart, dg2->Sd.dgpart, direrfnd, vl);
largerdir(dg1->Sd.dglast, dg2->Sd.dglast, direrfnd, vl);
break;
case kindOd:
largerdir(dg1->Sd.dgpart, dg2, direrfnd, vl);
largerdir(dg1->Sd.dglast, dg2, direrfnd, vl);
break;
}
break;
case kindOd:
switch (dg2->kind) {
case kindCd:
largerdir(dg1, dg2->Cd.dgfirst, direrfnd, vl);
largerdir(dg1, dg2->Cd.dgrest, direrfnd, vl);
break;
case kindSd:
largerdir(dg1, dg2->Sd.dgpart, direrfnd, vl);
largerdir(dg1, dg2->Sd.dglast, direrfnd, vl);
break;
case kindOd:
if (!*direrfnd && dg1->Od.basedir->kind != dg2->Od.basedir->kind &&
dg1->Od.basedir->kind != kindNON) {
error(14L, NULL, NULL, NULL, vl, false);
*direrfnd = true;
}
break;
}
break;
}
} /* largerdir */
Void compat(t1, t2, vl)
typcrec *t1, *t2;
val vl;
{
/* change unknown parts of t1 and t2 (as little as possible) (by becomes)
such that t2 after that can be enlarged to t1 (t2<t1)
vl: expression that causes the compat to be done */
typcrec *ht;
boolean direrfnd;
/* !! bij invullen van namen moet < / > gebruikt */
while (t2->kind == kindINDIR) t2 = t2->INDIR.tcind;
while (t1->kind == kindINDIR) t1 = t1->INDIR.tcind;
if (t2->kind == kindUNKNOWN) {
if (t1->kind == kindUNKNOWN)
{ if (t2->UNKNOWN.unknm != t1->UNKNOWN.unknm)
{ if (restrictable(t2->UNKNOWN.mustendemp, t2->UNKNOWN.mustconn, t1, vl))
becomes(t2, t1);
}
return;
}
if (occurs(t2->UNKNOWN.unknm, t1))
error(11L, t1, NULL, NULL, NULL, false);
else {
if (restrictable(t2->UNKNOWN.mustendemp, t2->UNKNOWN.mustconn, t1, vl))
becomes(t2, t1);
}
return;
}
switch (t1->kind) {
case kindUNKNOWN:
if (occurs(t1->UNKNOWN.unknm, t2))
error(11L, t2, NULL, NULL, NULL, false);
else {
if (restrictable(t1->UNKNOWN.mustendemp, t1->UNKNOWN.mustconn, t2, vl))
becomes(t1, t2);
}
break;
case kindSINGLEARROW:
if (t2->kind == kindSINGLEARROW) {
compat(t2->SINGLEARROW.tcarg, t1->SINGLEARROW.tcarg, vl);
compat(t1->SINGLEARROW.tcres, t2->SINGLEARROW.tcres, vl);
} else
error(12L, t2, t1, NULL, vl, false);
break;
case kindINT:
if (t2->kind != kindINT)
error(12L, t2, t1, NULL, vl, false);
break;
case kindFLOAT:
if (t2->kind != kindFLOAT)
error(12L, t2, t1, NULL, vl, false);
break;
case kindBOOL:
if (t2->kind != kindBOOL)
error(12L, t2, t1, NULL, vl, false);
break;
case kindSTRING:
if (t2->kind != kindSTRING)
error(12L, t2, t1, NULL, vl, false);
break;
case kindSYSTY:
if (t2->kind == kindSYSTY) {
direrfnd = false;
largerdir(t1->SYSTY.sysdirs, t2->SYSTY.sysdirs, &direrfnd, vl);
compat(t1->SYSTY.syscomp, t2->SYSTY.syscomp, vl);
} else
error(12L, t2, t1, NULL, vl, false);
break;
case kindAPS:
/* if t2^.kind = kindSYSTY
then compat(BuildSYSTY(BuildOd(BuildNON),BuildBUNDLE(ht)),t2,vl)
else */
if (t2->kind != kindAPS)
error(12L, t2, t1, NULL, vl, false);
break;
case kindCT:
if (t2->kind == kindCT) {
compat(t1->CT.tcfirst, t2->CT.tcfirst, vl);
compat(t1->CT.tcrest, t2->CT.tcrest, vl);
} else if (t2->kind == kindSOME) {
if (!occurs(t2->SOME.somnr, t1)) {
ht = BuildCT(t2->SOME.tcpart, BuildSOME(t2->SOME.tcpart, newname()));
becomes(t2, ht);
compat(t1, ht, vl);
} else
error(11L, t1, NULL, NULL, NULL, false);
} else
error(12L, t2, t1, NULL, vl, false);
break;
case kindLOC:
if (t2->kind == kindLOC) {
if (!(Equalsymbol(t2->LOC.locname, t1->LOC.locname) &&
t1->LOC.inst == t2->LOC.inst))
error(12L, t2, t1, NULL, vl, false);
} else
error(12L, t2, t1, NULL, vl, false);
break;
case kindBASETY:
if (t2->kind == kindBASETY) {
if (!(Equalsymbol(t2->BASETY.btname, t1->BASETY.btname) &&
t1->BASETY.bnr == t2->BASETY.bnr))
error(12L, t2, t1, NULL, vl, false);
} else
error(12L, t2, t1, NULL, vl, false);
break;
case kindSOME:
if (t2->kind == kindCT) {
if (!occurs(t1->SOME.somnr, t2)) {
ht = BuildCT(t1->SOME.tcpart, BuildSOME(t1->SOME.tcpart, newname()));
becomes(t1, ht);
compat(ht, t2, vl);
} else
error(11L, t2, NULL, NULL, NULL, false);
} else if (t2->kind == kindSOME) {
compat(t1->SOME.tcpart, t2->SOME.tcpart, vl);
if (t1->SOME.somnr != t2->SOME.somnr) {
if (!occurs(t1->SOME.somnr, t2)) {becomes(t1, t2);}
else error(11L, t1, NULL, NULL, NULL, false);
}
} else if (t2->kind == kindEMPTYT) {
if (!forfull)
becomes(t1, t2);
} else
error(12L, t2, t1, NULL, vl, false);
break;
case kindEMPTYT:
if (!forfull && t2->kind == kindSOME)
becomes(t2, t1);
else if (t2->kind != kindEMPTYT)
error(12L, t2, t1, NULL, vl, false);
break;
case kindALL:
/* ALL should not be treated here */
error(10L, NULL, NULL, Buildsymbol(
"compat ",
6L), NULL, false);
break;
}
} /* compat */
Static dirgraphrec *uplodir(islower_, dg1, dg2, direrfnd, vl)
boolean islower_;
dirgraphrec *dg1, *dg2;
boolean *direrfnd;
val vl;
{
/* delivers the largest lowerbound of dg1 and dg2 if islower is true,
delivers the smallest upperbound of dg1 and dg2 if islower is false
direrfnd: direction error already found and notified
vl: for which an error can be found */
dirgraphrec *Result;
switch (dg1->kind) {
case kindCd:
switch (dg2->kind) {
case kindCd:
Result = BuildCd(uplodir(islower_, dg1->Cd.dgfirst,
dg2->Cd.dgfirst, direrfnd, vl),
uplodir(islower_, dg1->Cd.dgrest,
dg2->Cd.dgrest, direrfnd, vl));
break;
case kindSd:
Result = BuildCd(uplodir(islower_, dg1->Cd.dgfirst,
dg2->Sd.dgpart, direrfnd, vl),
uplodir(islower_, dg1->Cd.dgrest, dg2, direrfnd, vl));
break;
case kindOd:
Result = BuildCd(uplodir(islower_, dg1->Cd.dgfirst, dg2, direrfnd,
vl), uplodir(islower_, dg1->Cd.dgrest,
dg2, direrfnd, vl));
break;
}
break;
case kindSd:
switch (dg2->kind) {
case kindCd:
Result = BuildCd(uplodir(islower_, dg1->Sd.dgpart,
dg2->Cd.dgfirst, direrfnd, vl),
uplodir(islower_, dg1, dg2->Cd.dgrest, direrfnd, vl));
break;
case kindSd:
Result = BuildSd(uplodir(islower_, dg1->Sd.dgpart,
dg2->Sd.dgpart, direrfnd, vl),
uplodir(islower_, dg1->Sd.dglast,
dg2->Sd.dglast, direrfnd, vl));
break;
case kindOd:
Result = BuildSd(uplodir(islower_, dg1->Sd.dgpart, dg2, direrfnd,
vl), uplodir(islower_, dg1->Sd.dglast,
dg2, direrfnd, vl));
break;
}
break;
case kindOd:
switch (dg2->kind) {
case kindCd:
Result = BuildCd(uplodir(islower_, dg1, dg2->Cd.dgfirst, direrfnd,
vl),
uplodir(islower_, dg1, dg2->Cd.dgrest, direrfnd, vl));
break;
case kindSd:
Result = BuildSd(uplodir(islower_, dg1, dg2->Sd.dgpart, direrfnd,
vl),
uplodir(islower_, dg1, dg2->Sd.dglast, direrfnd, vl));
break;
case kindOd:
if (islower_) {
if (dg1->Od.basedir->kind == dg2->Od.basedir->kind ||
dg2->Od.basedir->kind == kindNON)
Result = dg1;
else {
if (dg1->Od.basedir->kind == kindNON)
Result = dg2;
else {
if (!*direrfnd)
error(13L, NULL, NULL, NULL, vl, false);
*direrfnd = true;
Result = BuildOd(BuildNON());
}
}
} else if (dg1->Od.basedir->kind == dg2->Od.basedir->kind)
Result = dg1;
else
Result = BuildOd(BuildNON());
break;
}
break;
}
return Result;
} /* uplodir */
/* changes t1 and t2 (as little as needed) such that lower<ti
(largest lowerbound)
vl: the expression that causes this function to be called */
Static typcrec *lower PP((typcrec *t1, typcrec *t2, val vl));
typcrec *upper(t1, t2, vl)
typcrec *t1, *t2;
val vl;
{
/* changes t1 and t2 (as little as needed) such that upper>ti
(smallest upperbound)
vl: the expression that causes this procedure to be called */
typcrec *ht;
dirgraphrec *di;
boolean direrfnd;
/* !! invulling niet gedetailleerd genoeg */
while (t2->kind == kindINDIR) t2 = t2->INDIR.tcind;
while (t1->kind == kindINDIR) t1 = t1->INDIR.tcind;
if (t2->kind == kindUNKNOWN)
{ if (t1->kind == kindUNKNOWN)
{ if (t2->UNKNOWN.unknm != t1->UNKNOWN.unknm)
{ if (restrictable(t2->UNKNOWN.mustendemp, t2->UNKNOWN.mustconn, t1, vl))
becomes(t2, t1);
}
return t2;
}
if (occurs(t2->UNKNOWN.unknm, t1))
{error(11L, t1, NULL, NULL, NULL, false);
return BuildUNKNOWN(newname(),false,false);}
else
{ if (restrictable(t2->UNKNOWN.mustendemp, t2->UNKNOWN.mustconn, t1, vl))
becomes(t2, t1);
}
return t2;
}
switch (t1->kind) {
case kindUNKNOWN:
if (occurs(t1->UNKNOWN.unknm, t2))
{error(11L, t2, NULL, NULL, NULL, false);
return BuildUNKNOWN(newname(),false,false);}
else
{ if (restrictable(t1->UNKNOWN.mustendemp, t1->UNKNOWN.mustconn, t2, vl))
becomes(t1, t2);
}
break;
case kindSINGLEARROW:
if (t2->kind == kindSINGLEARROW)
return BuildSINGLEARROW(lower(t2->SINGLEARROW.tcarg, t1->SINGLEARROW.tcarg, vl),
upper(t1->SINGLEARROW.tcres, t2->SINGLEARROW.tcres, vl));
else
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindINT:
if (t2->kind != kindINT)
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindFLOAT:
if (t2->kind != kindFLOAT)
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindBOOL:
if (t2->kind != kindBOOL)
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindSTRING:
if (t2->kind != kindSTRING)
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindSYSTY:
if (t2->kind == kindSYSTY) {
direrfnd = false;
di = uplodir(false, t1->SYSTY.sysdirs, t2->SYSTY.sysdirs, &direrfnd,
vl);
ht = upper(t1->SYSTY.syscomp, t2->SYSTY.syscomp, vl);
if (direrfnd)
ht = BuildUNKNOWN(newname(), false, true);
return BuildSYSTY(di, ht);
} else
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
/*
else
if t2^.kind=APS
then
begin
compat(BuildSYSTY(BuildOd(BuildNON),BuildBUNDLE(ht)), t1,vl);
upper:=t2
end
else if t2^.kind=BUNDLE
then
begin
compat(BuildSYSTY(BuildCd(BuildOd(BuildIN),BuildOd(BuildOUT))
,
BuildBUNDLE(BuildCT(ht, t2^.typc4))
)
, t1
, vl);
upper:=t2
end
else if t2^.kind = EMPTYT
then
begin
compat(BuildSYSTY(BuildCd(BuildOd(BuildIN),BuildOd(BuildOUT))
, BuildBUNDLE(BuildCT(ht, t2))
)
, t1
, vl);
upper:=BuildBUNDLE(t2)
end
*/
break;
case kindAPS:
/* if t2^.kind = kindSYSTY
then compat(BuildSYSTY(BuildOd(BuildNON),BuildBUNDLE(ht)),t2,vl)
else */
if (t2->kind != kindAPS)
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindCT:
if (t2->kind == kindCT)
return BuildCT(upper(t1->CT.tcfirst, t2->CT.tcfirst, vl),
upper(t1->CT.tcrest, t2->CT.tcrest, vl));
else if (t2->kind == kindSOME) {
if (!occurs(t2->SOME.somnr, t1)) {
ht = BuildCT(t2->SOME.tcpart, BuildSOME(t2->SOME.tcpart, newname()));
becomes(t2, ht);
return upper(t1, ht, vl);
} else
{error(11L, t1, NULL, NULL, NULL, false);
return BuildUNKNOWN(newname(),false,false);}
} else
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindLOC:
if (t2->kind == kindLOC) {
if (!(Equalsymbol(t2->LOC.locname, t1->LOC.locname) &&
t1->LOC.inst == t2->LOC.inst))
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
} else
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindBASETY:
if (t2->kind == kindBASETY) {
if (!(Equalsymbol(t1->BASETY.btname, t2->BASETY.btname) &&
t1->BASETY.bnr == t2->BASETY.bnr))
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
} else
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindSOME:
if (t2->kind == kindCT)
{ if (!occurs(t1->SOME.somnr, t2))
{ ht = BuildCT(t1->SOME.tcpart, BuildSOME(t1->SOME.tcpart, newname()));
becomes(t1, ht);
return upper(ht, t2, vl);
} else
{error(11L, t2, NULL, NULL, NULL, false);
return BuildUNKNOWN(newname(),false,false);}
} else if (t2->kind == kindSOME)
{ht = BuildSOME(upper(t1->SOME.tcpart, t2->SOME.tcpart, vl),
t2->SOME.somnr);
if (t1->SOME.somnr != t2->SOME.somnr)
{ if (!occurs(t1->SOME.somnr, t2))
{becomes(t1, t2);} /* !! moet dit wel? */
else
{error(11L, t2, NULL, NULL, NULL, false);
return BuildUNKNOWN(newname(),false,false);}
}
return ht;
} else if (t2->kind == kindEMPTYT) {
if (!forfull) becomes(t1, t2);
} else
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindEMPTYT:
if (t2->kind == kindSOME) {
if (!forfull) becomes(t2, t1);
} else {
if (t2->kind != kindEMPTYT)
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
}
/*
else
if t2^.kind=LIST
then upper:=t2
else
if t2^.kind=BUNDLE
then upper:=BuildBUNDLE(upper(ht,t2^.typc4,vl))
else
if t2^.kind = SYSTY
then
begin
if forfull
then ht2:=BuildSOME(BuildUNKNOWN(newname),newname)
else ht2:=BuildEMPTYT;
compat(BuildSYSTY(BuildCd(BuildOd(BuildIN),BuildOd(BuildOUT))
, BuildBUNDLE(BuildCT(ht, ht2))
)
, t2
, vl);
upper:=BuildBUNDLE(t1)
end
*/
break;
case kindALL:
{error(10L, NULL, NULL, Buildsymbol( "upper", 5L), NULL, false);
return BuildUNKNOWN(newname(),false,false);}
break;
/* ALL should not be treated here */
}
return t1;
} /* upper */
typcrec *uppercomps(ty, vl)
typcrec *ty;
val vl;
{
/* ty must be composed of a number of the same parts; the result
is the smallest type larger than each part
vl: the expression that causes this to be called */
typcrec *un;
errorrec *erl;
typcrec *tp;
while (ty->kind == kindINDIR) ty = ty->INDIR.tcind;
if (ty->kind == kindUNKNOWN)
{ un = BuildUNKNOWN(newname(), false, ty->UNKNOWN.mustconn);
/* !! hier ook gevaar verkeerde invulling? */
becomes(ty, BuildSOME(un, newname()));
return un;
} else {
if (ty->kind == kindSOME) return (ty->SOME.tcpart);
else {
if (ty->kind == kindCT)
{ erl=errorlist;
tp = upper(ty->CT.tcfirst, uppercomps(ty->CT.tcrest, vl),
vl);
if (errorlist==erl) return tp;
else
{ error(17L, NULL, NULL, NULL, vl, false);
return tp;
}
}
else {
if (ty->kind != kindEMPTYT)
error(17L, NULL, NULL, NULL, vl, false);
return (BuildUNKNOWN(newname(), false, false));
}
}
}
} /* uppercomps */
Static typcrec *lower(t1, t2, vl)
typcrec *t1, *t2;
val vl;
{
typcrec *ht;
dirgraphrec *di;
boolean direrfnd;
/* !! invulling niet gedetaillerd genoeg */
while (t2->kind == kindINDIR) t2 = t2->INDIR.tcind;
while (t1->kind == kindINDIR) t1 = t1->INDIR.tcind;
if (t2->kind == kindUNKNOWN) {
if (t1->kind == kindUNKNOWN) {
if (t2->UNKNOWN.unknm != t1->UNKNOWN.unknm) {
if (restrictable(t2->UNKNOWN.mustendemp, t2->UNKNOWN.mustconn, t1, vl))
becomes(t2, t1);
}
return t2;
}
if (occurs(t2->UNKNOWN.unknm, t1))
{error(11L, t1, NULL, NULL, NULL, false);
return BuildUNKNOWN(newname(),false,false);}
else {
if (restrictable(t2->UNKNOWN.mustendemp, t2->UNKNOWN.mustconn, t1, vl))
becomes(t2, t1);
}
return t2;
}
switch (t1->kind) {
case kindUNKNOWN:
if (occurs(t1->UNKNOWN.unknm, t2))
{error(11L, t2, NULL, NULL, NULL, false);
return BuildUNKNOWN(newname(),false,false);}
else {
if (restrictable(t1->UNKNOWN.mustendemp, t1->UNKNOWN.mustconn, t2, vl))
becomes(t1, t2);
}
break;
case kindSINGLEARROW:
if (t2->kind == kindSINGLEARROW)
return BuildSINGLEARROW(upper(t2->SINGLEARROW.tcarg, t1->SINGLEARROW.tcarg, vl),
lower(t1->SINGLEARROW.tcres, t2->SINGLEARROW.tcres, vl));
else
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindINT:
if (t2->kind != kindINT)
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindFLOAT:
if (t2->kind != kindFLOAT)
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindBOOL:
if (t2->kind != kindBOOL)
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindSTRING:
if (t2->kind != kindSTRING)
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindSYSTY:
if (t2->kind == kindSYSTY) {
direrfnd = false;
di = uplodir(true, t1->SYSTY.sysdirs, t2->SYSTY.sysdirs, &direrfnd,
vl);
ht = lower(t1->SYSTY.syscomp, t2->SYSTY.syscomp, vl);
if (direrfnd)
ht = BuildUNKNOWN(newname(), false, true);
return BuildSYSTY(di, ht);
} else
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
/*
else
if t2^.kind=APS
then
compat(t1,BuildSYSTY(BuildOd(BuildNON),BuildBUNDLE(ht)),vl)
else if t2^.kind=BUNDLE
then
compat(t1,
BuildSYSTY(BuildCd(BuildOd(BuildIN),BuildOd(BuildOUT))
,
BuildBUNDLE(BuildCT(ht, t2^.typc4))
)
,vl)
*/
break;
case kindAPS:
/* if t2^.kind = SYSTY
then begin
compat(t2,BuildSYSTY(BuildOd(BuildNON),BuildBUNDLE(ht)),vl);
lower:=t2
end
else */
if (t2->kind != kindAPS)
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindCT:
if (t2->kind == kindCT)
return BuildCT(lower(t1->CT.tcfirst, t2->CT.tcfirst, vl),
lower(t1->CT.tcrest, t2->CT.tcrest, vl));
else if (t2->kind == kindSOME) {
if (!occurs(t2->SOME.somnr, t1)) {
ht = BuildCT(t2->SOME.tcpart, BuildSOME(t2->SOME.tcpart, newname()));
becomes(t2, ht);
return lower(t1, ht, vl);
} else
{error(11L, t1, NULL, NULL, NULL, false);
return BuildUNKNOWN(newname(),false,false);}
} else
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindLOC:
if (t2->kind == kindLOC) {
if (!(Equalsymbol(t2->LOC.locname, t1->LOC.locname) &&
t1->LOC.inst == t2->LOC.inst))
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
} else
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindBASETY:
if (t2->kind == kindBASETY) {
if (!(Equalsymbol(t1->BASETY.btname, t2->BASETY.btname) &&
t1->BASETY.bnr == t2->BASETY.bnr))
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
} else
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindSOME:
if (t2->kind == kindCT) {
if (!occurs(t1->SOME.somnr, t2)) {
ht = BuildCT(t1->SOME.tcpart, BuildSOME(t1->SOME.tcpart, newname()));
becomes(t1, ht);
return lower(ht, t2, vl);
} else
{error(11L, t2, NULL, NULL, NULL, false);
return BuildUNKNOWN(newname(),false,false);}
} else if (t2->kind == kindSOME) {
ht = BuildSOME(lower(t1->SOME.tcpart, t2->SOME.tcpart, vl),
t2->SOME.somnr);
if (t1->SOME.somnr != t2->SOME.somnr) {
if (!occurs(t1->SOME.somnr, t2)) becomes(t1, t2); /* !! moet dit wel? */
else
{error(11L, t2, NULL, NULL, NULL, false);
return BuildUNKNOWN(newname(),false,false);}
return ht;
}
} else if (t2->kind == kindEMPTYT) {
if (!forfull)
becomes(t1, t2);
} else
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
break;
case kindEMPTYT:
if (t2->kind == kindSOME) {
if (!forfull)
becomes(t2, t1);
} else {
if (t2->kind != kindEMPTYT) /* and (t2^.kind<>LIST) */
{error(12L, t2, t1, NULL, vl, false);
return BuildUNKNOWN(newname(),false,false);}
}
/* else if t2^.kind=BUNDLE
then lower:=lower(t1,t2^.typc4,vl) */
break;
case kindALL:
/* ALL needs not be treated here */
{error(10L, NULL, NULL, Buildsymbol( "lower", 5L), NULL, false);
return BuildUNKNOWN(newname(),false,false);}
break;
}
return t1;
} /* lower */